{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "7fa91a65-8fe3-4018-ad93-d8429322fe9f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "from torch import optim\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "from IPython.display import Image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "1f51fa59-340e-4c2c-bd25-d9b0a1f9ec78",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://aria42.com/images/bfgs.png\" width=\"400\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Image(url='https://aria42.com/images/bfgs.png', width=400)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "83a0a043-b392-4872-b7a4-fb685ae489b3",
   "metadata": {},
   "source": [
    "## basics"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "082de9de-31e3-4df8-be8b-055ebc414648",
   "metadata": {},
   "source": [
    "- references\n",
    "    - https://aria42.com/blog/2014/12/understanding-lbfgs\n",
    "    - https://colab.research.google.com/github/davidbau/how-to-read-pytorch/blob/master/notebooks/3-Pytorch-Optimizers.ipynb"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66368619-20fb-4667-98f3-a8112cfaced1",
   "metadata": {},
   "source": [
    "- L-BFGS（Limited-memory Broyden–Fletcher–Goldfarb–Shanno）：属于拟牛顿方法的一种，使用一阶导数信息构建目标函数的二阶近似，即使用梯度信息来近似Hessian矩阵（二阶导数矩阵）。这使得L-BFGS在非凸问题上比SGD表现更好，特别是在优化平滑或近似二次的目标函数时。\n",
    "- SGD：每次更新仅使用一个或少数几个样本计算的一阶导数（即梯度），而不构建目标函数的二阶近似。这意味着SGD可能需要更多的迭代次数来收敛，特别是在目标函数的形状复杂或非凸时。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b8e0b229-6228-4323-9e05-f3596944c8af",
   "metadata": {},
   "source": [
    "## case：Rosenbrock function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "8101eb70-61b2-4b65-b315-b1056f805f2c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2d Rosenbrock function\n",
    "def f(x):\n",
    "    return (1 - x[0]) ** 2 + 100 * (x[1] - x[0] ** 2) ** 2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1151eb98-bb70-4773-b86f-3934a9feb6a4",
   "metadata": {},
   "source": [
    "$$\n",
    "f(x,y)=(1-x)^2+100(y-x^2)^2\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "ad47b982-3cf3-44da-909f-22183c891ba9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Gradient descent\n",
    "x_gd = 10 * torch.ones(2, 1)\n",
    "# x_gd = torch.zeros(2, 1)\n",
    "x_gd.requires_grad = True\n",
    "gd = optim.SGD([x_gd], lr=1e-5)\n",
    "history_gd = []\n",
    "for i in range(100):\n",
    "    gd.zero_grad()\n",
    "    objective = f(x_gd)\n",
    "    objective.backward()\n",
    "    gd.step()\n",
    "    history_gd.append(objective.item())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "3552c025-e726-43c3-aee3-43f675dfe1d7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[1.9980e-03],\n",
       "        [2.4998e-07]], requires_grad=True)"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_gd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "00ce3bc2-cd93-4caa-8cb4-17a5d55fccbb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# L-BFGS\n",
    "def closure():\n",
    "    lbfgs.zero_grad()\n",
    "    objective = f(x_lbfgs)\n",
    "    objective.backward()\n",
    "    return objective\n",
    "\n",
    "\n",
    "x_lbfgs = 10 * torch.ones(2, 1)\n",
    "# x_lbfgs = torch.zeros(2, 1)\n",
    "x_lbfgs.requires_grad = True\n",
    "\n",
    "lbfgs = optim.LBFGS([x_lbfgs],\n",
    "                    history_size=10,\n",
    "                    max_iter=4,\n",
    "                    line_search_fn=\"strong_wolfe\")\n",
    "\n",
    "history_lbfgs = []\n",
    "for i in range(100):\n",
    "    history_lbfgs.append(f(x_lbfgs).item())\n",
    "    lbfgs.step(closure)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "5ac906e2-55b9-4187-8369-818867317f0d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[1.0000],\n",
       "        [1.0000]], requires_grad=True)"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_lbfgs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "5de49bfd-e2de-4a17-99d5-f8d21bae8a6a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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RsLDwwNDhw7Fxo0bYTabrfvwWvdceno6Fi1ahJCQEAiCgD179rT73JZrazAY8MgjjyAgIABeXl5YvHgxLly40PviROqxd999V3RzcxNfffVV8cSJE+KaNWtELy8v8fz581KX5tTmzZsnvvHGG+KxY8fEnJwcccGCBWJ4eLhYV1dn3ef5558XfXx8xPfee088evSouHz5cjE4OFisqamRsHLnduTIEXHIkCHihAkTxDVr1li381rbR1VVlRgRESGuXLlS/Oabb8S8vDxx3759Ym5urnUfXmv7eO6558RBgwaJn3zyiZiXlyfu3r1b9Pb2Frdu3Wrdh9e651JTU8UNGzaI7733nghA/OCDD9p9bsu1TUhIEENDQ8W0tDTxu+++E2NiYsSJEyeKLS0tvaqNoaYXbrjhBjEhIaHdttGjR4tPP/20RBW5prKyMhGAuH//flEURdFsNotBQUHi888/b92nqalJ9PPzE//xj39IVaZTq62tFUeMGCGmpaWJN910kzXU8Frbz1NPPSXOmjWry895re1nwYIF4gMPPNBu29KlS8V7771XFEVea3u6OtTYcm0vXbokurm5ie+++651n8LCQlGhUIiffvppr+rh7aceMhqNyMrKQmxsbLvtsbGxyMjIkKgq11RdXQ0A8Pf3BwDk5eWhpKSk3bXXaDS46aabeO176De/+Q0WLFiAW265pd12Xmv7+eijjxAdHY1ly5YhMDAQkydPxquvvmr9nNfafmbNmoXPP/8cp0+fBgB8//33OHjwIObPnw+A17ov2XJts7Ky0Nzc3G6fkJAQREVF9fr695sFLe2toqICJpMJWq223XatVouSkhKJqnI9oigiMTERs2bNQlRUFABYr29n1/78+fMOr9HZvfvuu/juu+/w7bffdviM19p+zp49i+3btyMxMRG//e1vceTIETz66KPQaDS47777eK3t6KmnnkJ1dTVGjx4NpVIJk8mETZs24e677wbAv9d9yZZrW1JSArVajYEDB3bYp7e/PxlqekkQhHbvRVHssI167uGHH8YPP/yAgwcPdviM1773CgoKsGbNGnz22Wdwd3fvcj9e694zm82Ijo7G5s2bAQCTJ0/G8ePHsX37dtx3333W/Xitey8lJQVvv/023nnnHYwbNw45OTlYu3YtQkJCEB8fb92P17rv9OTa2uP68/ZTDwUEBECpVHZIlWVlZR0SKvXMI488go8++ghffvklwsLCrNuDgoIAgNfeDrKyslBWVga9Xg+VSgWVSoX9+/fj73//O1QqlfV68lr3XnBwMMaOHdtu25gxY5Cfnw+Af6/t6YknnsDTTz+Nu+66C+PHj8eKFSvw2GOPISkpCQCvdV+y5doGBQXBaDTi4sWLXe7TUww1PaRWq6HX65GWltZue1paGmbMmCFRVa5BFEU8/PDDeP/99/HFF18gMjKy3eeRkZEICgpqd+2NRiP279/Pa99NP/vZz3D06FHk5ORYH9HR0bjnnnuQk5ODoUOH8lrbycyZMztMTXD69GlEREQA4N9re2poaIBC0f7Xm1KptA7p5rXuO7ZcW71eDzc3t3b7FBcX49ixY72//r3qZtzPtQ3pfu2118QTJ06Ia9euFb28vMRz585JXZpT+/Wvfy36+fmJX331lVhcXGx9NDQ0WPd5/vnnRT8/P/H9998Xjx49Kt59990cjmknV45+EkVea3s5cuSIqFKpxE2bNolnzpwR//nPf4qenp7i22+/bd2H19o+4uPjxdDQUOuQ7vfff18MCAgQn3zySes+vNY9V1tbK2ZnZ4vZ2dkiAHHLli1idna2dToTW65tQkKCGBYWJu7bt0/87rvvxJtvvplDuuXg5ZdfFiMiIkS1Wi1OmTLFOuyYeg5Ap4833njDuo/ZbBb/8Ic/iEFBQaJGoxHnzJkjHj16VLqiXcjVoYbX2n4+/vhjMSoqStRoNOLo0aPFHTt2tPuc19o+ampqxDVr1ojh4eGiu7u7OHToUHHDhg2iwWCw7sNr3XNffvllp/+Njo+PF0XRtmvb2NgoPvzww6K/v7/o4eEhLly4UMzPz+91bYIoimLv2nqIiIiIpMc+NUREROQSGGqIiIjIJTDUEBERkUtgqCEiIiKXwFBDRERELoGhhoiIiFwCQw0RERG5BIYaIiIicgkMNUREROQSGGqIiIjIJTDUEBERkUtgqCEiIiKX8P8BDTYR1TnLE/EAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plotting\n",
    "plt.semilogy(history_gd, label='GD')\n",
    "plt.semilogy(history_lbfgs, label='L-BFGS')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "327ca623-14e0-4744-b297-99c10be8f249",
   "metadata": {},
   "source": [
    "### cases: linear regression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "de68b117-34d9-4aa3-8aeb-b4eefd44797b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [1/10], Loss: 0.5054\n",
      "Epoch [2/10], Loss: 0.3055\n",
      "Epoch [3/10], Loss: 0.3011\n",
      "Epoch [4/10], Loss: 0.3004\n",
      "Epoch [5/10], Loss: 0.2997\n",
      "Epoch [6/10], Loss: 0.2990\n",
      "Epoch [7/10], Loss: 0.2983\n",
      "Epoch [8/10], Loss: 0.2977\n",
      "Epoch [9/10], Loss: 0.2970\n",
      "Epoch [10/10], Loss: 0.2964\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x7cc75dcefd60>"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAGdCAYAAADAAnMpAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAABGjklEQVR4nO3deVhU9f4H8PcwyqYwprEKOrgrrlcsMVFJRcW8GvrLbt3UFssbmkreFLUyN0zNi+aWZZqRWQma5loqS+YuqCViKijSEC4JLrEN5/fHxORxZpCBmTmzvF/Pw1PzmTPMh/Bx3n23IxMEQQARERGRRJykboCIiIgcG8MIERERSYphhIiIiCTFMEJERESSYhghIiIiSTGMEBERkaQYRoiIiEhSDCNEREQkqTpSN1AdFRUV+O233+Dh4QGZTCZ1O0RERFQNgiDg9u3b8Pf3h5OT4fEPmwgjv/32GwIDA6Vug4iIiGogNzcXAQEBBp+3iTDi4eEBQPPDeHp6StwNERERVUdRURECAwO1n+OG2EQYqZya8fT0ZBghIiKyMQ9bYsEFrERERCQphhEiIiKSFMMIERERScom1oxUhyAIKC8vh1qtlroVsmJ169aFXC6Xug0iIrqPXYSR0tJSqFQq3Lt3T+pWyMrJZDIEBASgfv36UrdCRER/sfkwUlFRgezsbMjlcvj7+8PZ2ZkHo5FegiDg2rVruHr1Klq2bMkREiIiK2HzYaS0tBQVFRUIDAyEu7u71O2QlfPy8kJOTg7KysoYRoiIrITdLGCt6phZokocNSMisj78BCciIiJJMYzYqJycHMhkMmRkZFT7NevXr0eDBg0k7wMAlEol4uPjTdoLERHZJoaRSmo1kJwMfPml5p8W2CKcm5uLl19+WbvwtmnTppg4cSJu3Ljx0NcGBgZCpVKhffv21X6/kSNH4vz587VpWTLmCFJERGQdGEYAICkJUCqB8HDguec0/1QqNXUzuXTpEkJCQnD+/Hl8+eWXuHDhAlavXo19+/YhNDQUN2/eNPja0tJSyOVy+Pr6ok6d6q9BdnNzg7e3tynaJyIiMhmGkaQkYMQI4OpVcT0vT1M3UyCJjo6Gs7Mz9u7di969e6NJkyYYNGgQfvjhB+Tl5WHGjBnaa5VKJebOnYsxY8ZAoVBg7NixeqdHtm3bhpYtW8LNzQ3h4eH47LPPIJPJcOvWLQC6owuzZs1C586d8fnnn0OpVEKhUODZZ5/F7du3tdfs3r0bPXv2RIMGDdCoUSM89dRTuHjxolE/a0FBAYYMGQI3NzcEBQXhiy++0LlmyZIl6NChA+rVq4fAwEC8/vrruHPnDgAgOTkZL774IgoLCyGTySCTyTBr1iwAQEJCAkJCQuDh4QFfX18899xzKCgoMKo/IiJH9m1GHj5Ju4TiMukODXXsMKJWAxMnAoKg+1xlbdIkk0/Z3Lx5E3v27MHrr78ONzc30XO+vr54/vnn8dVXX0G4r69Fixahffv2OHHiBN5++22d75mTk4MRI0Zg2LBhyMjIwGuvvSYKNIZcvHgRW7duxXfffYfvvvsOKSkpWLBggfb5u3fvIiYmBseOHcO+ffvg5OSEp59+GhUVFdX+eceMGYOcnBzs378fmzdvxsqVK3UCg5OTE5YtW4aff/4Zn332Gfbv34+33noLANCjRw/Ex8fD09MTKpUKKpUKU6ZMAaAZJZozZw5OnTqFrVu3Ijs7G2PGjKl2b0REjqpMXYFWM3dh4qYMzN2RiVO5tyTrxebPGamVtDTdEZH7CQKQm6u5rk8fk73tr7/+CkEQ0LZtW73Pt23bFn/88QeuXbumnVZ58skntR/AgCZ83G/16tVo3bo1Fi1aBABo3bo1fv75Z8ybN6/KXioqKrB+/Xp4eHgAAF544QXs27dP+7rhw4eLrl+7di28vb1x9uzZaq1XOX/+PHbt2oXDhw/j8ccf136PB3/2SZMmaf89KCgIc+bMwX/+8x+sXLkSzs7OUCgUkMlk8PX1Fb3upZde0v57s2bNsGzZMjz22GO4c+cOT1klIjIgU1WEQUvTRLUQZUOJunH0kRGVyrTXmUjliMj9Z2KEhIRU+ZqsrCx069ZNVHvsscce+l5KpVIbRADAz89PNGpx8eJFPPfcc2jWrBk8PT0RFBQEALhy5crDfxAAmZmZqFOnjqj/Nm3a6CxGPXDgAPr374/GjRvDw8MDo0aNwo0bN3D37t0qv396ejqGDh2Kpk2bwsPDA33+Co3V7Y+IyNEs2nNOFES6N2uInAWDIXeS7hwmxw4jfn6mva6aWrRoAZlMhrNnz+p9/ty5c3jkkUfw6KOPamv16tWr8nsKgqBzoJegb/rpAXXr1hU9lslkoimYIUOG4MaNG/j4449x5MgRHDlyBIBmeqQ69AWrB12+fBmRkZFo3749EhMTceLECaxYsQIAUFZWZvB1d+/eRUREBOrXr4+EhAQcO3YMW7ZsMao/IiJHUVpeAeW0HVhx4O91f6ue/wc2vRoqYVcajh1GwsKAgADA0AelTAYEBmquM6FGjRqhf//+WLlyJf7880/Rc/n5+fjiiy8wcuRIo04LbdOmDY4dOyaqHT9+vFZ93rhxA5mZmZg5cyb69u2rnT4yRtu2bVFeXi7qJSsrS7uotrLP8vJyfPDBB+jevTtatWqF3377TfR9nJ2dde7IfO7cOVy/fh0LFixAWFgY2rRpw8WrRER6nL56C61m7hLV0t/uj0EdTPs/2zXl2GFELgeWLtX8+4Mf/JWP4+M115nY8uXLUVJSggEDBiA1NRW5ubnYvXu3dqriYWs9HvTaa6/h3LlzmDp1Ks6fP4+vv/4a69evB1DzI9AfeeQRNGrUCGvWrMGFCxewf/9+xMTEGPU9WrdujYEDB2Ls2LE4cuQITpw4gVdeeUW0cLd58+YoLy/Hhx9+iEuXLuHzzz/H6tWrRd9HqVTizp072LdvH65fv4579+6hSZMmcHZ21r5u27ZtmDNnTo1+ViIiezX3u7P45/KD2sd9WnshZ8FgPFLPWcKuxGoVRuLi4iCTyUSLD/VJSUlB165d4erqimbNmul80EgqKgrYvBlo3FhcDwjQ1KOizPK2LVu2xPHjx9G8eXOMHDkSzZs3x6uvvorw8HAcOnQIDRsat5AoKCgImzdvRlJSEjp27IhVq1Zpd9O4uLjUqEcnJyds2rQJJ06cQPv27TF58mTtAlljrFu3DoGBgejduzeioqLw6quvis476dy5M5YsWYL3338f7du3xxdffIG4uDjR9+jRowfGjRuHkSNHwsvLCwsXLoSXlxfWr1+Pb775Bu3atcOCBQuwePHiGv2sRET2prhMDeW0Hfjkx2xtbe3oEKx/8eHrCS1NJlRnYYEex44dwzPPPANPT0+Eh4cbPNo7Ozsb7du3x9ixY/Haa6/h4MGDeP311/Hll1/q7NQwpKioCAqFAoWFhfD09BQ9V1xcjOzsbAQFBcHV1bUmP4qGWq3ZNaNSadaIhIWZZUTEkubNm4fVq1cjNzdX6lashsn+vBARWbGTV/5A1MqfRLVT70RA4V7XwCvMo6rP7/vVaGvvnTt38Pzzz+Pjjz/G3Llzq7x29erVaNKkiTastG3bFsePH8fixYurHUYsQi436fZdKaxcuRLdunVDo0aNcPDgQSxatAjjx4+Xui0iIrKgmVvPIOHw3zsKIzv4YuXzXSXs6OFqFEaio6MxePBg9OvX76Fh5NChQ4iIiBDVBgwYgLVr16KsrExnNwcAlJSUoKSkRPu4qKioJm06nF9//RVz587FzZs30aRJE7z55puIjY2Vui0iIrKAP0vVaPvOblFtw0uPoVcrL4k6qj6jw8imTZtw8uRJnZ0bhuTn58PHx0dU8/HxQXl5Oa5fvw4/Pdtm4+Li8N577xnbmsP73//+h//9739St0FERBZ25NINjFxzWFQ7MysCHq6WnZapKaMWsObm5mLixIlISEgwar7d0PkXhnZ5xMbGorCwUPvFNQ9ERET6TfnmlCiIPN2lMXIWDLaZIAIYOTJy4sQJFBQUoGvXv+ee1Go1UlNTtVtV5Q8s+vT19UV+fr6oVlBQgDp16qBRo0Z638fFxaXGO0CIiIgcwd2ScgS/u0dU2zj2cfRo/qiBV1gvo8JI3759cebMGVHtxRdfRJs2bTB16lSdIAIAoaGh2L59u6i2d+9ehISE6F0vQkRERFX78dfr+PfaI6La2dkD4O5sm7ecM6prDw8PnZuj1atXD40aNdLWY2NjkZeXhw0bNgAAxo0bh+XLlyMmJgZjx47FoUOHsHbtWnz55Zcm+hGIiIgcx/iNJ/Hd6b/vmfavxwIRF9VRwo5qz+QRSqVSiW5SFhQUhJ07d2Ly5MlYsWIF/P39sWzZMuva1ktERGTliorL0HHWXlFt87hQSe+2ayq1DiPJycmix5VHkN+vd+/eOHnyZG3fioiIyCEdyCrAi+vEu1jPzRkI17q2fThnJce+N42V6tOnz0OP2Del9evXo0GDBgafz8nJgUwmQ0ZGBgBNAJXJZKKb3RERkXm88tlxURAZ00OJnAWD7SaIAAwjkhkzZgxkMpnO14ULF5CUlCS64ZtSqdQ5bv9hAcKcevToAZVKBYVCIcn7ExE5glv3SqGctgM/ZP6urW2NfgKz/hksYVfmYZvLbu3EwIEDsW7dOlHNy8tL764ka+Ls7AxfX1+p2yAislt7fsnHa5+fENWy5g6ESx3r/nyoKY6MSMjFxQW+vr6iL7lcLpqm6dOnDy5fvozJkydrR0+Sk5Px4osvorCwUFubNWsWAKC0tBRvvfUWGjdujHr16uHxxx/Xu66nSZMmcHd3x9NPP40bN24Y1feD0zSVozR79uxB27ZtUb9+fQwcOBAqlUr0unXr1qFt27ZwdXVFmzZtsHLlypr8ZyMismv//uSIKIiM690cOQsG220QAexwZEQQBPxZppbkvd3qyg2eKltTSUlJ6NSpE1599VWMHTsWANCwYUPEx8fjnXfeQVZWFgCgfv36ADTnvuTk5GDTpk3w9/fHli1bMHDgQJw5cwYtW7bEkSNH8NJLL2H+/PmIiorC7t278e6779a6z3v37mHx4sX4/PPP4eTkhH//+9+YMmUKvvjiCwDAxx9/jHfffRfLly9Hly5dkJ6ejrFjx6JevXoYPXp0rd+fiMjW3bhTgq5zfxDVvpvQE+0b2/+UuN2FkT/L1Gj3zp6HX2gGxh44891332lDBAAMGjQI33zzjeiahg0bQi6Xw8PDQzQ1olAoIJPJRLWLFy/iyy+/xNWrV+Hv7w8AmDJlCnbv3o1169Zh/vz5WLp0KQYMGIBp06YBAFq1aoWffvoJu3eLb65krLKyMqxevRrNmzcHAIwfPx6zZ8/WPj9nzhx88MEHiIqKAqDZ8n327Fl89NFHDCNE5PC+O/0bxm9M1z6u4yRD5pyBqCt3jAkMuwsjtiQ8PByrVq3SPq5Xr16tvt/JkychCAJatWolqpeUlGiP3s/MzMTTTz8tej40NLTWYcTd3V0bRADAz88PBQUFAIBr164hNzcXL7/8snZ0BwDKy8u5CJaIHJogCBix+hBOXP5DW5vYtyUm929Vxavsj92FEbe6cpydPUCy9zZGvXr10KJFC5O9f0VFBeRyOU6cOKGzCLZyBKbyJoWm9uDR/jKZTPteFRUVADRTNY8//rjoOmtfrEtEZC4FRcV4bP4+UW3PpF5o7eshUUfSsbswIpPJbPZsfkOcnZ2hVqsfWuvSpQvUajUKCgoQFham93u1a9cOhw+LbzP94GNT8/HxQePGjXHp0iU8//zzZn0vIiJbkHTyKmK+PqV9XN+lDjLe6Y86DjIt8yD7+tS2U0qlEqmpqXj22Wfh4uKCRx99FEqlEnfu3MG+ffvQqVMnuLu7o1WrVnj++ecxatQofPDBB+jSpQuuX7+O/fv3o0OHDoiMjMQbb7yBHj16YOHChRg2bBj27t1b6yma6pg1axbeeOMNeHp6YtCgQSgpKcHx48fxxx9/ICYmxuzvT0RkDQRBwFMf/ohffivS1t4a2Bqv9zHdKLktcswIZmNmz56NnJwcNG/eHF5eXgA0B4+NGzcOI0eOhJeXFxYuXAhAs3121KhRePPNN9G6dWv885//xJEjRxAYGAgA6N69Oz755BN8+OGH6Ny5M/bu3YuZM2ea/Wd45ZVX8Mknn2D9+vXo0KEDevfujfXr1yMoKMjs701EZA1UhX8iKHanKIjse7O3wwcRAJAJ5lpEYEJFRUVQKBQoLCyEp6en6Lni4mJkZ2cjKCgIrq6uEnVItoJ/XohICpuOXsG0pDPax14eLjgc2xdyJ9MeB2Ftqvr8vh+naYiIiMxEEAT0XZKCS9fuamtvP9UOL/fkqPD9GEaIiIjMIPfmPYQtPCCqpfy3D5o2qt0xDvaIYYSIiMjENhzKwTvf/qJ93KShO5Kn9IGTnU/L1BTDCBERkYlUVAh44v39UBUWa2tzhrXHC92bStiV9WMYISIiMoGc63fRZ3GyqPbj1HAEPOIuTUM2xG7CiA1sCiIrwD8nRGQOH6dewrydmdrHrXzqY8+kXia/eaq9svkwUnkM+b179+Dm5iZxN2TtSktLAfAYeiIyDXWFgJC53+OPe2Xa2sLhHfFMt0AJu7I9Nh9G5HI5GjRooL0pm7u7O5Mo6VVRUYFr167B3d0dderY/B99IpLYhYLb6LckVVQ7HNsXvgqeYWQsu/gb2dfXFwC0gYTIECcnJzRp0oSBlYhqZfn+X7F473nt404BCmyNfoJ/t9SQXYQRmUwGPz8/eHt7o6ys7OEvIIfl7OwMJyfeBYGIaqZcXYEWM3aJavEjO2NYl8YSdWQf7CKMVJLL5VwLQEREZrE1PQ+TvsoQ1Y7N6AcvDxdpGrIjdhVGiIiIzEE5bYfoccN6zjj5dn+JurE/HK8mIiIy4F5puU4QeaqjH4OIiXFkhIiISI8vj15B7H132gWAH2J6o4V3fYk6sl8MI0RERA94cDQEAHIWDJagE8fAaRoiIqK/FBWX6QSRZ7sFMoiYGUdGiIiIAHz6YzZmf3dWVEv9bziaNOK9ZcyNYYSIiBwep2WkxWkaIiJyWH/cLdUJIi89EcQgYmEcGSEiIoe04sAFLNqTJaodin0SfgredNXSGEaIiMjhcFrGunCahoiIHEbB7WKdIDLhyRYMIhLjyAgRETmExXuysPzABVGN95axDgwjRERk9zgtY90YRoiIyG79dutP9FiwX1SbOrAN/tOnuUQdkT5GrRlZtWoVOnbsCE9PT3h6eiI0NBS7du0yeH1ycjJkMpnO17lz52rdOBERUVVmbftFJ4hkvNOfQcQKGTUyEhAQgAULFqBFixYAgM8++wxDhw5Feno6goODDb4uKysLnp6e2sdeXl41bJeIiOjhOC1jW4wKI0OGDBE9njdvHlatWoXDhw9XGUa8vb3RoEGDGjVIRERUXVdu3EOvRQdEtVlD2mHME0ESdUTVUeM1I2q1Gt988w3u3r2L0NDQKq/t0qULiouL0a5dO8ycORPh4eFVXl9SUoKSkhLt46Kiopq2SUREDuK/35zCNyeuimpnZkXAw7WuRB3ZALUaSEsDVCrAzw8ICwPkcou3YXQYOXPmDEJDQ1FcXIz69etjy5YtaNeund5r/fz8sGbNGnTt2hUlJSX4/PPP0bdvXyQnJ6NXr14G3yMuLg7vvfeesa0REZGD4rRMDSQlARMnAlfvC3ABAcDSpUBUlEVbkQmCIBjzgtLSUly5cgW3bt1CYmIiPvnkE6SkpBgMJA8aMmQIZDIZtm3bZvAafSMjgYGBKCwsFK09ISIix3ah4Db6LUkV1RYO74hnugVK1JGNSEoCRowAHowAMpnmn5s3mySQFBUVQaFQPPTz2+gw8qB+/fqhefPm+Oijj6p1/bx585CQkIDMzMxqv0d1fxgiInIc0RtPYsdplah2dvYAuDvz1IoqqdWAUikeEbmfTKYZIcnOrvWUTXU/v2v9GxMEQTSK8TDp6enw8/Or7dsSEZGDEgQBQbE7deqclqmmtDTDQQTQjJbk5mqu69PHIi0ZFUamT5+OQYMGITAwELdv38amTZuQnJyM3bt3AwBiY2ORl5eHDRs2AADi4+OhVCoRHByM0tJSJCQkIDExEYmJiab/SYiIyO6d/a0IkcvSRLVl/+qCf3byl6gjG6RSPfwaY64zAaPCyO+//44XXngBKpUKCoUCHTt2xO7du9G/f38AgEqlwpUrV7TXl5aWYsqUKcjLy4ObmxuCg4OxY8cOREZGmvanICIiuzfq06NIPX9NVDs3ZyBc61p+94dNq+7shAVnMWq9ZsQSuGaEiMhx6ZuWqecsxy+zB0rUkY2rXDOSl6e7gBWQZM2IUcfBExERWVJG7i2dIPLRC10ZRGpDLtds3wX+3j1TqfJxfLxFzxvhkmMiIrJKw1f9hBOX/xDVfp03CHXlEv1/tJUcEGYSUVGa7bv6zhmJj7f4OSMMI0REZFUqKgQ0my4eDfFTuOJQbF+JOoJVHRBmMlFRwNChVhGwuGaEiIisxpFLNzByzWFRbcNLj6FXKwlvsGqhA8LskcUOPbMEhhEiIvs34H+pyPr9tqh2cX4k5E4yA6+wAAseEGaPuICViIhsgrpCgHLaDlEQaeVTHzkLBksbRADjDgijGuOaESIikkzq+WsY9elRUe2rV7vj8WaNJOroAVZ4QJg9YhghIiJJhMbtg6qwWFS7ND8STlKPhtzPCg8Is0ecpiEiIosqU1dAOW2HKIh0bfoIchYMtq4gAmh2lwQE6J7HUUkmAwIDNddRjTGMEBGRxez9JR8tZ+wS1ba83gOJ/+khUUcPYYUHhNkjTtMQEZFFtH93D+6UlItq2XGRkBkadbAWVnZAmD1iGCEiIrMqLlOjzdu7RbVerbyw4aXHJOqoBqzogDB7xDBCRERm821GHiZuyhDVdr4Rhnb+NnhmlFwO9OkjdRd2iWGEiIjMQjlth07NJqZlyOK4gJWIiEzqXmm5ThAZ3MEPOQsGM4iQXhwZISIik/n6WC7eSjwtqv0Q0xstvOtL1BHZAoYRIiIyCX3TMjkLBkvQCdkaTtMQEVGt3C4u0wkiz4QEMIhQtXFkhIhsh1rNrZVWZv3BbMzaflZUS/lvHzRtVE+ijsgWMYwQkW1IStJ/6NTSpTx0SiKcliFT4TQNEVm/pCRgxAjdW7nn5WnqSUnS9OWgbt0r1QkiY3ooGUSoxmSCIAhSN/EwRUVFUCgUKCwshKenDR6UQ0Q1p1YDSqVuEKkkk2lGSLKzOWVjASuTL2Dh7ixR7adpT8K/gZtEHZE1q+7nN6dpiMi6paUZDiIAIAhAbq7mOp6OaVacliFz4TQNEVk3lcq015HRrt0u0Qki0eHNGUTIZDgyQkTWzc/PtNeRUT7Ym4UP918Q1Y7O6AtvD1eJOiJ7xDBCRNYtLEyzJiQvTzMl86DKNSNhYZbvzc5xWoYshdM0RGTd5HLN9l1AEzzuV/k4Pp6LV01IVfinThD574DWDCJkNgwjRGT9oqKAzZuBxo3F9YAATZ3njJjM7O1nERq3X1RLf7s/osNbSNQROQJO0xCRbYiKAoYO5QmsZsRpGZIKwwgR2Q65nNt3zSD35j2ELTwgqr07pB1efCJIoo7I0TCMEBE5sGmJp7HpWK6odnpWBDxd60rUETkihhEiIgfFaRmyFgwjREQO5kLBHfRbkiKqLYjqgGcfayJRR+ToGEaIiBzI+I0n8d1p8Wm1Z2cPgLszPw5IOvzTR0TkAARBQFDsTp06p2XIGjCMEBHZuUxVEQYtTRPVlj7bGUM7NzbwCiLLYhghIrJjL647igNZ10S1c3MGwrUuz2ch68EwQkRkh/RNy7jWdcK5OYMk6ojIMKOOg1+1ahU6duwIT09PeHp6IjQ0FLt27aryNSkpKejatStcXV3RrFkzrF69ulYNExFR1U7l3tIJIqv/3ZVBhKyWUSMjAQEBWLBgAVq00Nyj4LPPPsPQoUORnp6O4OBgneuzs7MRGRmJsWPHIiEhAQcPHsTrr78OLy8vDB8+3DQ/ARERaf3f6p9wLOcPUe383EFwrsNbkZH1kgmCvntyV1/Dhg2xaNEivPzyyzrPTZ06Fdu2bUNmZqa2Nm7cOJw6dQqHDh2q9nsUFRVBoVCgsLAQnp6etWmXiMguVVQIaDZdPBri7eGCozP6SdQRUfU/v2u8ZkStVuObb77B3bt3ERoaqveaQ4cOISIiQlQbMGAA1q5di7KyMtStq/+44ZKSEpSUlGgfFxUV1bRNIiK7dzT7Jp75SPw/eOtf7IY+rb0l6ojIOEaHkTNnziA0NBTFxcWoX78+tmzZgnbt2um9Nj8/Hz4+PqKaj48PysvLcf36dfj5+el9XVxcHN577z1jWyMicjgD41NxLv+2qHZh3iDUkXNahmyH0X9aW7dujYyMDBw+fBj/+c9/MHr0aJw9e9bg9TKZTPS4clbowfr9YmNjUVhYqP3Kzc01eC0RkSMqV1dAOW2HKIi08K6PnAWDGUTI5hg9MuLs7KxdwBoSEoJjx45h6dKl+Oijj3Su9fX1RX5+vqhWUFCAOnXqoFGjRgbfw8XFBS4uLsa2RkTkEL44chkztvwsqm16tTu6NzP89yqRNav1OSOCIIjWd9wvNDQU27dvF9X27t2LkJAQg+tFiIjIMH132r00PxJOToZHm4msnVFjedOnT0daWhpycnJw5swZzJgxA8nJyXj++ecBaKZXRo0apb1+3LhxuHz5MmJiYpCZmYlPP/0Ua9euxZQpU0z7UxAR2bmScrXeIJLTqQhOqSmAWi1BV0SmYdTIyO+//44XXngBKpUKCoUCHTt2xO7du9G/f38AgEqlwpUrV7TXBwUFYefOnZg8eTJWrFgBf39/LFu2jGeMEBEZYU3qRczfeU5UW5m6BpGHtv1dCAgAli4FoqIs3B1R7dX6nBFL4DkjROSo9I2GZC8cAtmDf3VXbgrYvJmBhKxGdT+/ueSaiMgK3Sst1z8t88U43SACAJW1SZM4ZUM2h2GEiMjKLNmbhXbv7BHV1r3YDTkD6wFXrxp+oSAAublAWpqZOyQyLd61l4jIiuidlomL1JzNdHJf9b6JSmXirojMiyMjRERWoKi4TP+0zILBfx8SaeDUah3VvY7ISnBkhIhIYu9t/wXrDuaIal+92h2PP3iIWViYZtdMXt7fa0TuJ5Npng8LM1+zRGbAMEJEjkWt1qypUKk0IwhhYYBcLlk7hkZD9JLLNdt3R4zQBI/7A0nl6El8vKQ/D1FNcJqGiBxHUhKgVALh4cBzz2n+qVRq6hZ2826pThDxdK1jOIhUiorSbN9t3FhcDwjgtl6yWTxnhIgcQ1KSZkTBCs7nePPrU0g8Kd4VszX6CXQObFD9b2JlIzxE+lT385thhIjsn1qtGQExtC22cq1FdrbZP9CNmpYhsnE89IyIqFJamuTnc/xeVKwTRJo2cmcQIQIXsBKRI6juuRtmOp/jH3O+x827paLankm90NrXwyzvR2RrGEbIfnAOnQyR8HwOTssQPRynacg+WNEuCbJCledzVC5WfZBMBgQGmvR8jqz82wwiRNXEkRGyfYZ2SeTlaerc7kgWPp9DXwjZ8UZPBPsrTPL9iewNR0bItqnVwMSJ+k+j5F1M6X4WOp/D0GgIgwiRYRwZIdtmzC6JPn0s1hZZqagoYOhQs6wtysi9hWErDopqrnWdcG7OoFp/byJ7xzBCtk3iXRJkg+RykwdTfaMh+97sjeZe9U36PkT2imGEbBvvYkoS4yJVotrjmhGybRLskiACgJ8uXtcJIo0buDGIENUAR0bItvEupiQBfaMhP04NR8Aj7hJ0Q2T7ODJCto93MSULMjQtwyBCVHMcGSH7YMZdEkQA8MPZ3/HKhuOiWscABbaN7ylRR0T2g2GE7IcZdkkQAfpHQ47N6AcvDxcJuiGyPwwjRERV4G4ZIvPjmhEiIj2+zcjTCSK9W3kxiBCZAUdGiIgeoG805NQ7EVC415WgGyL7xzBCRPQXQRAQFLtTp87RECLzYhghoppTq+1mB9MXRy5jxpafRbVhnf0R/2wXiToichwMI0RUM0lJmjsm33+jwoAAzSF0Nna2i75pmV/eG4B6LvwrksgSuICViIyXlKQ59fbBOybn5WnqSUnS9GWkigrB4G4ZBhEiy2EYISLjqNWaEZH7j96vVFmbNElznRVblXwRzaaL14eMDm3K9SFEEmD0JyLjpKXpjojcTxCA3FzNdVZ6CJ2+0ZCsuQPhUsc217sQ2TqGESIyjkpl2ussqExdgZYzdunUORpCJC2GESIyjp+faa+zkPd3n8Oq5Iui2ht9WyKmfyvzv7kd7ToiMgeGESIyTliYZtdMXp7+dSMymeb5sDDL92aAvmmZC/MGoY7cAsvm7GjXEZG5cAErERlHLtd8kAKa4HG/ysfx8Vbxf/7FZWqDu2UsFkTsYNcRkbkxjBCR8aKigM2bgcaNxfWAAE3dCv6P/7mPD6PN27tFtZmD21pufYid7DoisgSjwkhcXBy6desGDw8PeHt7Y9iwYcjKyqryNcnJyZDJZDpf586dq1XjRCSxqCggJwc4cADYuFHzz+xsqwgiymk78NPFG6LapfmReCWsmeWaMGbXEZGDM2rNSEpKCqKjo9GtWzeUl5djxowZiIiIwNmzZ1GvXr0qX5uVlQVPT0/tYy8vr5p1TETWQy63qu27hX+WodN7e3XqkuyWseFdR0SWZlQY2b1bPOS5bt06eHt748SJE+jVq1eVr/X29kaDBg2MbpCIqDr6L0nBrwV3RLUpEa0w/smW0jRko7uOiKRQq900hYWFAICGDRs+9NouXbqguLgY7dq1w8yZMxEeHm7w2pKSEpSUlGgfFxUV1aZNIrJz+hapZsdFQvbgAltLssFdR0RSqfECVkEQEBMTg549e6J9+/YGr/Pz88OaNWuQmJiIpKQktG7dGn379kVqaqrB18TFxUGhUGi/AgMDa9omEdmxgtvFBnfLSBpEAJvadUQkNZkg6IvsDxcdHY0dO3bgxx9/REBAgFGvHTJkCGQyGbZt26b3eX0jI4GBgSgsLBStOyEix9V59l7culcmqs0ZGowXQpXSNGSIvnNGAgM1QcQKFvsSmVNRUREUCsVDP79rNE0zYcIEbNu2DampqUYHEQDo3r07EhISDD7v4uICFxeXmrRGRA7A0GiIVYqKAoYO5QmsRFUwKowIgoAJEyZgy5YtSE5ORlBQUI3eND09HX5ctEVERsq9eQ9hCw/o1K02iFSysl1HRNbGqDASHR2NjRs34ttvv4WHhwfy8/MBAAqFAm5ubgCA2NhY5OXlYcOGDQCA+Ph4KJVKBAcHo7S0FAkJCUhMTERiYqKJfxQismf6RkOWPtsZQzs31nM1EdkSo8LIqlWrAAB9Hkj469atw5gxYwAAKpUKV65c0T5XWlqKKVOmIC8vD25ubggODsaOHTsQGRlZu86JyGHY1LQMERmtxgtYLam6C2CIyL5cKLiNfkt0d94xiBDZBrMuYCUiMjd9oyFrR4egb1sfCbohInNiGCEiq8NpGSLHwrv2EpHVOH31FoMIkQPiyAgRWQV9IeSrV7vj8WaNJOiGiCyJYYSIJMfRECLHxmkaIpLMTxevM4gQEUdGiEga+kLIdxN6on1jhQTdEJGUGEaIyOI4GkJE9+M0DRFZzPdnf2cQISIdHBkhIovQF0L2vdkbzb3qS9ANEVkThhEiMjuOhhBRVThNQ0RmsyX9KoMIET0UR0aIyCz0hZCD055E4wZuEnRDRNaMYYSITI6jIURkDE7TEJHJrD+YrRNEHq3vwiBCRFXiyAgRmYS+0ZDjM/vh0fouEnRDRLaEYYSIakUQBATF7tSpczSEiKqL0zREVGNfHr2iE0Ta+nkyiBCRUTgyQkQ1om9a5vSsCHi61pWgGyKyZQwjRGSUigoBzaZzWoaITIfTNERUbWtSL+oEkRe6N2UQIaJa4cgIEVWLvmmZc3MGwrWuXIJuiMieMIwQUZXK1BVoOWOXTp2jIURkKgwjRGTQ4j1ZWH7ggqg2PrwFpgxoLVFHRGSPGEaISC990zK/zhuEunIuNSMi0+LfKkQkUlymNnhvGQYRIjIHjowQkdbbW3/G54cvi2rTI9vg1V7NJeqIiBwBwwgRAdA/LXNpfiScnGQSdENEjoRhhMjWqNVAWhqgUgF+fkBYGCCv+fbauyXlCH53j06du2WIyFIYRohsSVISMHEicPXq37WAAGDpUiAqyuhvN+HLdGw/9ZuoFhfVAf96rEltOyUiqjaGESJbkZQEjBgBCIK4npenqW/ebFQg0Tctkx0XCZmM0zJEZFlcGk9kC9RqzYjIg0EE+Ls2aZLmuoe4da/U4G4ZBhEikgJHRohsQVqaeGrmQYIA5OZqruvTx+BlL6w9grRfr4tqH/6rC4Z08jdRo0RExmMYIbIFKlWtrzM0GkJEJDVO0xDZAj+/Gl9XUFTMIEJEVo0jI0S2ICxMs2smL0//uhGZTPN8WJioPHhZGn75rUhUWzemG8LbeJuzWyIiozCMENkCuVyzfXfECE3wuD+QVC46jY8XnTfC0RAishWcpiGyFVFRmu27jRuL6wEBom29uTfvMYgQkU0xKozExcWhW7du8PDwgLe3N4YNG4asrKyHvi4lJQVdu3aFq6srmjVrhtWrV9e4YSKHFhUF5OQABw4AGzdq/pmdrQ0ioXH7ELbwgOglX73anUGEiKyaUdM0KSkpiI6ORrdu3VBeXo4ZM2YgIiICZ8+eRb169fS+Jjs7G5GRkRg7diwSEhJw8OBBvP766/Dy8sLw4cNN8kMQORS5XO/2XY6GEJGtkgmCvtVw1XPt2jV4e3sjJSUFvXr10nvN1KlTsW3bNmRmZmpr48aNw6lTp3Do0KFqvU9RUREUCgUKCwvh6elZ03aJ7NKFgtvotyRVp84gQkRSq+7nd60WsBYWFgIAGjZsaPCaQ4cOISIiQlQbMGAA1q5di7KyMtStW1fnNSUlJSgpKdE+Lioq0rmGiIBWM3ehtLxCVNs2/gl0DGggTUNERDVQ4wWsgiAgJiYGPXv2RPv27Q1el5+fDx8fH1HNx8cH5eXluH79ut7XxMXFQaFQaL8CAwNr2iaR3VJO26ETRHIWDGYQISKbU+MwMn78eJw+fRpffvnlQ6998H4XlTNDhu6DERsbi8LCQu1Xbm5uTdsksjs/5xXqrA9xknFahohsV42maSZMmIBt27YhNTUVAQEBVV7r6+uL/Px8Ua2goAB16tRBo0aN9L7GxcUFLi4uNWmNyK7pW6T6/eReaOnjIUE3RESmYVQYEQQBEyZMwJYtW5CcnIygoKCHviY0NBTbt28X1fbu3YuQkBC960WISD/uliEie2XUNE10dDQSEhKwceNGeHh4ID8/H/n5+fjzzz+118TGxmLUqFHax+PGjcPly5cRExODzMxMfPrpp1i7di2mTJliup+CyI4dy7mpE0S8PVwYRIjIbhg1MrJq1SoAQJ8HzjhYt24dxowZAwBQqVS4cuWK9rmgoCDs3LkTkydPxooVK+Dv749ly5bxjBGiatA3GpL2VjgCG7pL0A0RkXnU6pwRS+E5I+SIOC1DRLauup/fvDcNkZU5kFWgE0Ta+HowiBCR3eJde4msiL7RkKPT+8Lb01WCboiILINhhMhKcFqGiBwVp2mIJHbo4g2dINKjeSMGESJyGBwZIZKQvtGQM7Mi4OHKM3iIyHEwjBBJQBAEBMXu1KlzNISIHBGnaYgs7MC5Ap0gMrFvSwYRInJYHBkhsiB90zKZswfCzVkuQTdERNaBYYTIAioqBDSbzmkZIiJ9GEaIzGzHaRWiN54U1WYObotXwppJ1BERkXVhGCEyI33TMllzB8KlDqdliIgqMYwQmYG6QkBzTssQEVULwwiRiX19PBdvbT4tqsVFdcC/HmsiUUdERNaNYYTIhPRNy1yYNwh15NxFT0RkCMMIkQmUlleg1cxdOnVOyxARPRzDCFEtrTuYjfe2nxXVlj7bGUM7N5aoIyIi28IwQlQL+qZlLs2PhJOTTIJuiIhsE8OIo1CrgbQ0QKUC/PyAsDBAzu2lNVVcpkabt3fr1DktQ0RkPIYRR5CUBEycCFy9+nctIABYuhSIipKuLxv14b5f8cH350W1T0aFoF87H4k6Ir0YwIlsBsOIvUtKAkaMAARBXM/L09Q3b2YgMYK+aZnsuEjIZJyWsSoM4EQ2hfsN7ZlarfkL+cEgAvxdmzRJcx1V6U5Jud4gkrNgMIOItakM4PcHEeDvAJ6UJE1fRGQQw4g9S0vT/Qv5foIA5OZqriOD4nZmov27e0S1L155nOtDrBEDOJFN4jSNPVOpTHudAzI0GmIWXONQe8YE8D59LNYWEVWNIyP2zM/PtNc5kMJ7ZTpBxLmOk/mCSFISoFQC4eHAc89p/qlUckrBWAzgRDaJIyP2LCxMs2gvL0//sLVMpnk+LMzyvVmx6VvOYOORK6Ja4n96oGvTR8zzhlxkbDoM4EQ2SSYI+j6lrEtRUREUCgUKCwvh6ekpdTu2pfKDDhB/2FUuuuQHnYhFp2UAzdSMUml4aqEyMGZnc8qmOir/ez4sgPO/J5FFVPfzm9M09i4qShM4Gj9wNHlAAIPIfa7dLtEJIr6eruZfpMpFxqYll2u27wJ/B+5KlY/j4xlEiKwMp2kcQVQUMHQoF0caMH7jSXx3WryGYMcbPRHsrzD/m3ONg+lVBnB954zExzOAE1khhhFHIZdz94AeFp+WeRDXOJgHAziRTWEYIetlxq2uebf+xBML9otqbXw9sHtSL5N8/2rjImPzYQAnshkMI2SdzHic96hPjyL1/DVR7YeY3mjhXb9W37dGKtc4jBihCR76FhlzjQMR2TkuYCXrY8bjvJXTdugEkZwFg6UJIpW4yJiIHBy39pJ1MdNW15zrd9FncbKo9nhQQ3z1WmjNezU1nsBKRHamup/fnKYh62KG47yHLv8Rp64Wit/mrXAENnSvRaNmwDUOROSgGEbIuph4q6vku2WIiOihuGaErIuJtrpm5d/WCSIR7XwYRIiIrBBHRsi6mGCra+9FB3D5xj1R7cj0vvDxdDV1t0REZAJGj4ykpqZiyJAh8Pf3h0wmw9atW6u8Pjk5GTKZTOfr3LlzNe2Z7Fktj/NWTtuhE0RyFgxmECEismJGh5G7d++iU6dOWL58uVGvy8rKgkql0n61bNnS2LcmR1GDra6ncm/pTMuM6BrAaRkiIhtg9DTNoEGDMGjQIKPfyNvbGw0aNDD6deSgjDjOu+OsPSgqLhfVTr7dHw3rOVuqWyIiqgWLrRnp0qULiouL0a5dO8ycORPh4eEGry0pKUFJSYn2cVFRkSVaJGtTja2u3C1DRGT7zL6bxs/PD2vWrEFiYiKSkpLQunVr9O3bF6mpqQZfExcXB4VCof0KDAw0d5tkY45cuqETRMb0UDKIEBHZoFqdwCqTybBlyxYMGzbMqNcNGTIEMpkM27Zt0/u8vpGRwMBAnsBKAPSPhpyeFQFP17oSdENERIZY9Qms3bt3R0JCgsHnXVxc4OLiYsGOyBYIgoCg2J06dY6GEBHZNkkOPUtPT4dfdQ+3IgKQnFWgE0TeeLIFgwgRkR0wemTkzp07uHDhgvZxdnY2MjIy0LBhQzRp0gSxsbHIy8vDhg0bAADx8fFQKpUIDg5GaWkpEhISkJiYiMTERNP9FGTX9E3LnJ09AO7OPLOPiMgeGP23+fHjx0U7YWJiYgAAo0ePxvr166FSqXDlyhXt86WlpZgyZQry8vLg5uaG4OBg7NixA5GRkSZon+wZp2WIiBxDrRawWkp1F8CQ/Th55Q9ErfxJVJsR2RZjezWTqCMiIjKWVS9gJarKsBUHkZF7S1TLmjsQLnX0HwFPRES2jWGErEZFhYBm08XTMo0buOHgtCcl6oiIiCyBYYSswqGLN/Cvjw+Lap+//BjCWnpJ1BEREVkKwwhJrt+SFFwouCOqXZwfCbmTzMAriIjInjCMkGTK1RVoMWOXqNbG1wO7J/WSqCMiIpICwwhJIjmrAGPWHRPVvn4tFI8FNZSoIyIikgrDCFnc4/N/wO9FJaLapfmRcOK0DBGRQ2IYIYspLa9Aq5niaZluykfwzbgeEnVERETWgGHElqnVQFoaoFIBfn5AWBggt86zOHb/nI9xCSdEtW+jn0CnwAbSNERERFaDYcRWJSUBEycCV6/+XQsIAJYuBaKipOtLj7Zv78afZWpRLTsuEjIZp2WIiEiiu/ZSLSUlASNGiIMIAOTlaepJSdL09YDiMjWU03aIgkh4ay/kLBjMIEJERFq8N42tUasBpVI3iFSSyTQjJNnZkk7ZfJuRh4mbMkS1XRPD0NbPwX9/REQOhPemsVdpaYaDCAAIApCbq7muTx+LtXU/5bQdOjXeaZeIiAzhNI2tUalMe50J3Sst1wkiT3X0YxAhIqIqcWTE1vj5mfY6E9l09AqmJZ0R1X6I6Y0W3vUt2gcREdkexw0jNrQtViQsTLMmJC9PMyXzoMo1I2FhFmuJ0zJERFQbjjlNk5SkWQQaHg4895zmn0ql1exCqZJcrtm+C2iCx/0qH8fHWyRYFRWX6QSRZ7sFMogQEZFRHC+M2Mi22CpFRQGbNwONG4vrAQGaugXOGVl3MBsdZ+0V1dLeCseC4R3N/t5ERGRfHGtrr41si602iaaaOC1DRETVwa29+tjAtlijyOUW7fOPu6XoMud7Ue3lnkF4+6l2FuuBiIjsj2OFESveFmvtVhy4gEV7skS1Q7FPwk/hJlFHRERkLxwrjFjptlhrx2kZIiIyJ8dawFq5LdbQfVFkMiAw0KLbYq1Zwe1inSAy4ckWDCJERGRSjjUyUrktdsQITfC4f+2uhbfFWrtFe85hxYGLotqxGf3g5eEiUUdERGSvHGtkBLCKbbHWTjlth04QyVkwmEGEiIjMwrFGRipFRQFDh9rmCaxm9NutP9FjwX5RberANvhPn+YSdURERI7AMcMIYPFtsdbuve2/YN3BHFEt453+aODuLE1DRETkMBw3jJAWd8sQEZGUGEYc2JUb99Br0QFR7b1/BmN0D6U0DRERkUNiGHFQb20+ha+Pi0+jPTMrAh6udSXqiIiIHBXDiAPitAwREVkThhEHcqHgDvotSRHVFg7viGe6BUrUEREREcOIw4j+4iR2nBHfc+fs7AFwd+YfASIikhY/ieycIAgIit2pU+e0DBERWQuGETuWc/0u+ixOFtWW/asL/tnJX5qGiIiI9GAYsVNxOzPxUeolUe383EFwruN4dwAgIiLrxjBiZ/RNy4S39sK6Fx+TqCMiIqKqMYzYkQsFt9FvSaqotnlcKEKUDSXqiIiI6OGMHrNPTU3FkCFD4O/vD5lMhq1btz70NSkpKejatStcXV3RrFkzrF69uia9UhXe+fZnnSByYd4gBhEiIrJ6RoeRu3fvolOnTli+fHm1rs/OzkZkZCTCwsKQnp6O6dOn44033kBiYqLRzZKuigoBymk7sOHQZW1tcAc/5CwYjDpyrg8hIiLrZ/Q0zaBBgzBo0KBqX7969Wo0adIE8fHxAIC2bdvi+PHjWLx4MYYPH27s29N9zuUXYWB8mqj2bfQT6BTYQJqGiIiIasDsa0YOHTqEiIgIUW3AgAFYu3YtysrKULeu7r1QSkpKUFJSon1cVFRk7jZtzoZDOXjn219EtYvzIyF3kknUERERUc2YfRw/Pz8fPj4+opqPjw/Ky8tx/fp1va+Ji4uDQqHQfgUG8rjyShUVAp5YsF8UREZ0DUDOgsEMIkREZJMssqhAJhN/SAqCoLdeKTY2FoWFhdqv3Nxcs/doC3Ku30Wz6TuRd+tPbe3HqeFY/H+dJOyKiIiodsw+TePr64v8/HxRraCgAHXq1EGjRo30vsbFxQUuLi7mbs2mfJJ2CXN3ZGoft/Suj72TexkMdERERLbC7GEkNDQU27dvF9X27t2LkJAQvetFSExdIaDbvB9w826ptvb+8A4Y2a2JhF0RERGZjtHTNHfu3EFGRgYyMjIAaLbuZmRk4MqVKwA0UyyjRo3SXj9u3DhcvnwZMTExyMzMxKeffoq1a9diypQppvkJ7NiFgjtoPn2nKIgcju3LIEJERHbF6JGR48ePIzw8XPs4JiYGADB69GisX78eKpVKG0wAICgoCDt37sTkyZOxYsUK+Pv7Y9myZdzW+xArDlzAoj1Z2scdAxT4NvoJTssQEZHdkQmVq0mtWFFRERQKBQoLC+Hp6Sl1O2ZVrq5Ah1l78WeZWlv738hOeLpLgIRdERERGa+6n9+8N40V0XeI2dEZfeHt4SpRR0RERObHMGIlPtibhQ/3X9A+fiyoIb56tTunZYiIyO4xjEistLwCrWbuEtVWPPcPDO7oJ1FHRERElsUwIqGf8wrx1Ic/imon3+6PhvWcJeqIiIjI8hhGJBK3MxMfpV7SPg5r+Sg+f/lxCTsiIiKSBsOIhRWXqdHm7d2i2poXuiIi2FeijoiIiKTFMGJB6Vf+wNMrfxLVMt7pjwbunJYhIiLHxTBiIe9++zM+O3RZ+ziinQ/WjAqRsCMiIiLrwDBiZn+WqtH2HfG0zPoXu6FPa2+JOiIiIrIuDCNmdCznJv5v9SFR7fSsCHi68gaBRERElRhGzGTq5tP46niu9vHQzv5Y+mwXCTsiIiKyTgwjJna3pBzB7+4R1b545XE80eJRiToiIiKybgwjJvTThet47pMjotov7w1APRf+ZyYiIjKEn5ImMmlTOrZm/KZ9PDIkEO+P6ChhR0RERLaBYaSWiorL0HHWXlHt69dC8VhQQ4k6IiIisi0MI7WQnFWAMeuOiWqZswfCzVkuUUdERES2h2Gkhl77/Dj2/PK79vHo0KZ4b2h7CTsiIiKyTQwjRiq8V4ZOs8XTMlte74EuTR6RqCMiIiLbxjBihO/P/o6xG46LaufmDIRrXU7LEBER1RTDSDWN+vQoUs9f0z5+rVczxEa2lbAjIiIi+8Aw8hA375biH3O+F9W+m9AT7RsrJOqIiIjIvjCMVGHHaRWiN54U1c7PHQTnOk4SdURERGR/GEb0EAQBI9ccxtHsm9rahCdb4M2I1hJ2RUREZJ8YRh5QcLsYj83bJ6rtnhSGNr6eEnVERERk3xhG7rM1PQ+TvsrQPnarK8eZWRGoI+e0DBERkbkwjEAzLTN0xUGcvlqorU2JaIXxT7aUsCsiIiLH4PBhJL+wGN3jxNMyP8T0QgtvD4k6IiIiciwOHUbOXC3EkOU/ah83queMozP6Qe4kk7ArIiIix+LQYeTbjDztv88c3BavhDWTsBsiIiLH5NBh5JWwZvD2dEFEO18oH60ndTtEREQOyaHDiK/CFa/2ai51G0RERA6Ne1aJiIhIUgwjREREJCmGESIiIpIUwwgRERFJimGEiIiIJMUwQkRERJKqURhZuXIlgoKC4Orqiq5duyItLc3gtcnJyZDJZDpf586dq3HTREREZD+MDiNfffUVJk2ahBkzZiA9PR1hYWEYNGgQrly5UuXrsrKyoFKptF8tW/ImdERERFSDMLJkyRK8/PLLeOWVV9C2bVvEx8cjMDAQq1atqvJ13t7e8PX11X7J5fIaN01ERET2w6gwUlpaihMnTiAiIkJUj4iIwE8//VTla7t06QI/Pz/07dsXBw4cqPLakpISFBUVib6IiIjIPhkVRq5fvw61Wg0fHx9R3cfHB/n5+Xpf4+fnhzVr1iAxMRFJSUlo3bo1+vbti9TUVIPvExcXB4VCof0KDAw0pk0iIiKyITW6N41MJhM9FgRBp1apdevWaN26tfZxaGgocnNzsXjxYvTq1Uvva2JjYxETE6N9XFRUxEBCRERkp4waGXn00Uchl8t1RkEKCgp0Rkuq0r17d/z6668Gn3dxcYGnp6foi4iIiOyTUSMjzs7O6Nq1K77//ns8/fTT2vr333+PoUOHVvv7pKenw8/Pr9rXC4IAAFw7QkREZEMqP7crP8cNMXqaJiYmBi+88AJCQkIQGhqKNWvW4MqVKxg3bhwAzRRLXl4eNmzYAACIj4+HUqlEcHAwSktLkZCQgMTERCQmJlb7PW/fvg0AnKohIiKyQbdv34ZCoTD4vNFhZOTIkbhx4wZmz54NlUqF9u3bY+fOnWjatCkAQKVSic4cKS0txZQpU5CXlwc3NzcEBwdjx44diIyMrPZ7+vv7Izc3Fx4eHgbXpuhTudYkNzeXUz1WiL8f68ffkXXj78f6OfrvSBAE3L59G/7+/lVeJxMeNnZiw4qKiqBQKFBYWOiQfwisHX8/1o+/I+vG34/14++oenhvGiIiIpIUwwgRERFJyq7DiIuLC9599124uLhI3Qrpwd+P9ePvyLrx92P9+DuqHrteM0JERETWz65HRoiIiMj6MYwQERGRpBhGiIiISFIMI0RERCQpuwsjcXFx6NatGzw8PODt7Y1hw4YhKytL6rbIgLi4OMhkMkyaNEnqVug+eXl5+Pe//41GjRrB3d0dnTt3xokTJ6Rui/5SXl6OmTNnIigoCG5ubmjWrBlmz56NiooKqVtzWKmpqRgyZAj8/f0hk8mwdetW0fOCIGDWrFnw9/eHm5sb+vTpg19++UWaZq2Q3YWRlJQUREdH4/Dhw/j+++9RXl6OiIgI3L17V+rW6AHHjh3DmjVr0LFjR6lbofv88ccfeOKJJ1C3bl3s2rULZ8+exQcffIAGDRpI3Rr95f3338fq1auxfPlyZGZmYuHChVi0aBE+/PBDqVtzWHfv3kWnTp2wfPlyvc8vXLgQS5YswfLly3Hs2DH4+vqif//+2nuvOTq739p77do1eHt7IyUlBb169ZK6HfrLnTt38I9//AMrV67E3Llz0blzZ8THx0vdFgGYNm0aDh48iLS0NKlbIQOeeuop+Pj4YO3atdra8OHD4e7ujs8//1zCzggAZDIZtmzZgmHDhgHQjIr4+/tj0qRJmDp1KgCgpKQEPj4+eP/99/Haa69J2K11sLuRkQcVFhYCABo2bChxJ3S/6OhoDB48GP369ZO6FXrAtm3bEBISgv/7v/+Dt7c3unTpgo8//ljqtug+PXv2xL59+3D+/HkAwKlTp/Djjz8adQNSspzs7Gzk5+cjIiJCW3NxcUHv3r3x008/SdiZ9TD6rr22RBAExMTEoGfPnmjfvr3U7dBfNm3ahJMnT+LYsWNSt0J6XLp0CatWrUJMTAymT5+Oo0eP4o033oCLiwtGjRoldXsEYOrUqSgsLESbNm0gl8uhVqsxb948/Otf/5K6NdIjPz8fAODj4yOq+/j44PLly1K0ZHXsOoyMHz8ep0+fxo8//ih1K/SX3NxcTJw4EXv37oWrq6vU7ZAeFRUVCAkJwfz58wEAXbp0wS+//IJVq1YxjFiJr776CgkJCdi4cSOCg4ORkZGBSZMmwd/fH6NHj5a6PTJAJpOJHguCoFNzVHYbRiZMmIBt27YhNTUVAQEBUrdDfzlx4gQKCgrQtWtXbU2tViM1NRXLly9HSUkJ5HK5hB2Sn58f2rVrJ6q1bdsWiYmJEnVED/rvf/+LadOm4dlnnwUAdOjQAZcvX0ZcXBzDiBXy9fUFoBkh8fPz09YLCgp0Rkscld2tGREEAePHj0dSUhL279+PoKAgqVui+/Tt2xdnzpxBRkaG9iskJATPP/88MjIyGESswBNPPKGzHf78+fNo2rSpRB3Rg+7duwcnJ/Ff33K5nFt7rVRQUBB8fX3x/fffa2ulpaVISUlBjx49JOzMetjdyEh0dDQ2btyIb7/9Fh4eHtq5OoVCATc3N4m7Iw8PD531O/Xq1UOjRo24rsdKTJ48GT169MD8+fPxzDPP4OjRo1izZg3WrFkjdWv0lyFDhmDevHlo0qQJgoODkZ6ejiVLluCll16SujWHdefOHVy4cEH7ODs7GxkZGWjYsCGaNGmCSZMmYf78+WjZsiVatmyJ+fPnw93dHc8995yEXVsRwc4A0Pu1bt06qVsjA3r37i1MnDhR6jboPtu3bxfat28vuLi4CG3atBHWrFkjdUt0n6KiImHixIlCkyZNBFdXV6FZs2bCjBkzhJKSEqlbc1gHDhzQ+9kzevRoQRAEoaKiQnj33XcFX19fwcXFRejVq5dw5swZaZu2InZ/zggRERFZN7tbM0JERES2hWGEiIiIJMUwQkRERJJiGCEiIiJJMYwQERGRpBhGiIiISFIMI0RERCQphhEiIiKSFMMIERERSYphhIiIiCTFMEJERESSYhghIiIiSf0//Zn7mRTyqvoAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Hyper-parameters\n",
    "input_size = 1\n",
    "output_size = 1\n",
    "num_epochs = 10\n",
    "\n",
    "# Toy dataset\n",
    "x_train = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168], \n",
    "                    [9.779], [6.182], [7.59], [2.167], [7.042], \n",
    "                    [10.791], [5.313], [7.997], [3.1]], dtype=np.float32)\n",
    "\n",
    "y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573], \n",
    "                    [3.366], [2.596], [2.53], [1.221], [2.827], \n",
    "                    [3.465], [1.65], [2.904], [1.3]], dtype=np.float32)\n",
    "\n",
    "# Linear regression model\n",
    "model = nn.Linear(input_size, output_size)\n",
    "\n",
    "# Loss and optimizer\n",
    "criterion = nn.MSELoss()\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=1e-2)  \n",
    "\n",
    "# Train the model\n",
    "for epoch in range(num_epochs):\n",
    "    # Convert numpy arrays to torch tensors\n",
    "    inputs = torch.from_numpy(x_train)\n",
    "    targets = torch.from_numpy(y_train)\n",
    "\n",
    "    # Forward pass\n",
    "    outputs = model(inputs)\n",
    "    loss = criterion(outputs, targets)\n",
    "    \n",
    "    # Backward and optimize\n",
    "    optimizer.zero_grad()\n",
    "    loss.backward()\n",
    "    optimizer.step()\n",
    "    \n",
    "    \n",
    "    print ('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))\n",
    "\n",
    "# Plot the graph\n",
    "predicted = model(torch.from_numpy(x_train)).detach().numpy()\n",
    "plt.plot(x_train, y_train, 'ro', label='Original data')\n",
    "plt.plot(x_train, predicted, label='Fitted line')\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "32437a47-3706-4c4c-9fc0-84e835f3a882",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [1/10], Loss: 0.1689\n",
      "Epoch [2/10], Loss: 0.1689\n",
      "Epoch [3/10], Loss: 0.1689\n",
      "Epoch [4/10], Loss: 0.1689\n",
      "Epoch [5/10], Loss: 0.1689\n",
      "Epoch [6/10], Loss: 0.1689\n",
      "Epoch [7/10], Loss: 0.1689\n",
      "Epoch [8/10], Loss: 0.1689\n",
      "Epoch [9/10], Loss: 0.1689\n",
      "Epoch [10/10], Loss: 0.1689\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x7cc75dd73fd0>"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Hyper-parameters\n",
    "input_size = 1\n",
    "output_size = 1\n",
    "num_epochs = 10\n",
    "learning_rate = 0.001\n",
    "\n",
    "# Toy dataset\n",
    "x_train = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168], \n",
    "                    [9.779], [6.182], [7.59], [2.167], [7.042], \n",
    "                    [10.791], [5.313], [7.997], [3.1]], dtype=np.float32)\n",
    "\n",
    "y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573], \n",
    "                    [3.366], [2.596], [2.53], [1.221], [2.827], \n",
    "                    [3.465], [1.65], [2.904], [1.3]], dtype=np.float32)\n",
    "\n",
    "# Linear regression model\n",
    "model = nn.Linear(input_size, output_size)\n",
    "\n",
    "# Loss and optimizer\n",
    "criterion = nn.MSELoss()\n",
    "\n",
    "lbfgs = optim.LBFGS(model.parameters())\n",
    "\n",
    "inputs = torch.from_numpy(x_train)\n",
    "targets = torch.from_numpy(y_train)\n",
    "\n",
    "def closure():\n",
    "    lbfgs.zero_grad()\n",
    "    outputs = model(inputs)\n",
    "    # print(inputs, outputs, targets)\n",
    "    loss = criterion(outputs, targets)\n",
    "    loss.backward()\n",
    "    return loss\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    lbfgs.step(closure)\n",
    "\n",
    "    pred = model(inputs)\n",
    "    loss = criterion(pred, targets)\n",
    "    print ('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))\n",
    "\n",
    "# Plot the graph\n",
    "predicted = model(torch.from_numpy(x_train)).detach().numpy()\n",
    "plt.plot(x_train, y_train, 'ro', label='Original data')\n",
    "plt.plot(x_train, predicted, label='Fitted line')\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a505d8ec-9b4e-4157-a6bf-4c7a7a35c6bd",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
